{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Object Mutability"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Certain Python built-in object types (aka data types) are **mutable**.\n",
    "\n",
    "That is, the internal contents (state) of the object in memory can be modified."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3]\n",
      "0x1cf6ab5b208\n"
     ]
    }
   ],
   "source": [
    "my_list = [1, 2, 3]\n",
    "print(my_list)\n",
    "print(hex(id(my_list)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n",
      "0x1cf6ab5b208\n"
     ]
    }
   ],
   "source": [
    "my_list.append(4)\n",
    "print(my_list)\n",
    "print(hex(id(my_list)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, the memory address of *my_list* has **not** changed.\n",
    "\n",
    "But, the **contents** of *my_list* has changed from *[1, 2, 3]* to *[1, 2, 3, 4]*."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "On the other hand, consider this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3]\n",
      "0x1cf6abd55c8\n"
     ]
    }
   ],
   "source": [
    "my_list_1 = [1, 2, 3]\n",
    "print(my_list_1)\n",
    "print(hex(id(my_list_1)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 2, 3, 4]\n",
      "0x1cf6ab56888\n"
     ]
    }
   ],
   "source": [
    "my_list_1 = my_list_1 + [4]\n",
    "print(my_list_1)\n",
    "print(hex(id(my_list_1)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice here that the memory address of *my_list_1* **did** change."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is because concatenating two lists objects *my_list_1* and *[4]* did not modify the contents of *my_list_1* - instead it created a new list object and re-assigned *my_list_1* to reference this new object."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similarly with **dictionary** objects that are also **mutable** types."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'key1': 'value 1'}\n",
      "0x1cf6abdcdc8\n"
     ]
    }
   ],
   "source": [
    "my_dict = dict(key1='value 1')\n",
    "print(my_dict)\n",
    "print(hex(id(my_dict)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'key1': 'modified value 1'}\n",
      "0x1cf6abdcdc8\n"
     ]
    }
   ],
   "source": [
    "my_dict['key1'] = 'modified value 1'\n",
    "print(my_dict)\n",
    "print(hex(id(my_dict)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'key1': 'modified value 1', 'key2': 'value 2'}\n",
      "0x1cf6abdcdc8\n"
     ]
    }
   ],
   "source": [
    "my_dict['key2'] = 'value 2'\n",
    "print(my_dict)\n",
    "print(hex(id(my_dict)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once again we see that while we are modifying the **contents** of the dictionary, the memory address of *my_dict* has not changed."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Now consider the immutable sequence type: **tuple**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The tuple is immutable, so elements cannot be added, removed or replaced."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "t = (1, 2, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This tuple will **never** change at all. It has three elements, the integers 1, 2, and 3. This will remain the case as long as **t**'s reference is not changed."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But, consider the following tuple:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "a = [1, 2]\n",
    "b = [3, 4]\n",
    "t = (a, b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, **t** is still immutable, i.e. it contains a reference to the object **a** and the object **b**. **That** will never change as long as **t**'s reference is not re-assigned.\n",
    "\n",
    "**However**, the elements **a** and **b** are, themselves, mutable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "([1, 2, 3], [3, 4, 5])\n"
     ]
    }
   ],
   "source": [
    "a.append(3)\n",
    "b.append(5)\n",
    "print(t)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Observe that the contents of **a** and **b** **did** change!\n",
    "\n",
    "So immutability can be a little more subtle than just thinking something can never change. \n",
    "\n",
    "The tuple **t** did **not** change - it contains two elements, that are the references **a** and **b**. And that will not change. But, because the referenced elements are mutable themselves, it appears as though the tuple has changed.\n",
    "\n",
    "It hasn't though - that distinction is subtle but important to understand!"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
